home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Libraries / BlobMgr / Demo Folder / Lib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  11.1 KB  |  502 lines  |  [TEXT/KAHL]

  1. /*
  2.  * Blob Manager Demonstration:  library routines
  3.  */
  4.  
  5. # include    "BlobMgr.h"
  6. # include    "BlobDemo.h"
  7.  
  8.  
  9. static short    charBlobSize = 18;
  10.  
  11. /*
  12.  * StrCpy copies the second argument into the first.
  13.  * StrCat appends the second argument to the first.
  14.  *
  15.  * Both assume Pascal-style strings.
  16.  */
  17.  
  18.  
  19. void
  20. StrCpy (StringPtr dst, StringPtr src)
  21. {
  22. short        i;
  23.  
  24.     for (i = 0; i <= src[0]; ++i)
  25.         dst[i] = src[i];
  26. }
  27.  
  28.  
  29. void
  30. StrCat (StringPtr dst, StringPtr src)
  31. {
  32. short        i, dlen, slen;
  33.  
  34.     slen = src[0];
  35.     dlen = dst[0];
  36.     for (i = 1; slen > 0; ++i, --slen)
  37.         dst[dlen + i] = src[i];
  38.     dst[0] += src[0];
  39. }
  40.  
  41.  
  42. /*
  43.  * MovesLeft creates a string that says "n Moves Left"
  44.  */
  45.  
  46. void
  47. MovesLeft (short n, StringPtr s)
  48. {
  49.     NumToString (n, s);
  50.     StrCat (s, (n == 1 ? "\p Move Left" : "\p Moves Left"));
  51. }
  52.  
  53.  
  54. /*
  55.  * Draw vertical button blob.  It's assumed the font to draw in is the
  56.  * current font.
  57.  *
  58.  * The static region (the button frame) is not drawn gray when the button
  59.  * is unhilited (unlike most blobs), to simulate behavior of regular push
  60.  * buttons.  For this reason, the bProcManualDimMask flag is set in the flags word.
  61.  */
  62.  
  63. static pascal void
  64. DrawVButtonBlob (BlobHandle bDst, BlobHandle bSrc, short partCode)
  65. {
  66. StringHandle    hStr;
  67. StringPtr        title;
  68. FontInfo    fInfo;
  69. Rect        r;
  70. RGBColor    gray;
  71. short        cHeight;    /* character height */
  72. short        tHeight;    /* title height */
  73. short        h, v;
  74. short        i;
  75. short        savedTextMode;
  76.  
  77.     if (partCode == inStatBlob)                    /* draw frame */
  78.     {
  79.         FrameRgn ((**bDst).statRgn);
  80.     }
  81.     else                                        /* draw text inside frame */
  82.     {
  83.         /*
  84.          * Draw text of source blob in the drag region of the
  85.          * destination blob
  86.          */
  87.         FillRgn ((**bDst).dragRgn, white);
  88.         hStr = (StringHandle) GetBRefCon (bSrc);    /* text from source */
  89.         if (hStr == (StringHandle) nil)
  90.             return;
  91.         HLock ((Handle) hStr);
  92.         title = *hStr;
  93.         GetFontInfo (&fInfo);
  94.         cHeight = fInfo.ascent + fInfo.descent;
  95.         tHeight = title[0] * (cHeight + fInfo.leading) - fInfo.leading;
  96.         r = BDragBox (bDst);                        /* drag box of dest */
  97.         v = (r.top + r.bottom - tHeight ) / 2 + fInfo.ascent;
  98.         /*
  99.          * Check whether to draw in gray or not.  If so, and RGB gray is
  100.          * available, set the transfer mode.
  101.          */
  102.         if (GetBDrawMode (bDst, partCode) == dimDraw)
  103.             (void) BeginBlobDimDraw (bDst, partCode);
  104.         for (i = 1; i <= title[0]; ++i)
  105.         {
  106.             h = (r.left + r.right - CharWidth (title[i])) / 2;
  107.             MoveTo (h, v);
  108.             DrawChar (title[i]);
  109.             v += cHeight + fInfo.leading;
  110.         }
  111.         if (GetBDrawMode (bDst, partCode) == dimDraw)
  112.             EndBlobDimDraw ();
  113.         HUnlock ((Handle) hStr);
  114.     }
  115. }
  116.  
  117.  
  118. /*
  119.  * Make a simulated push button.  It looks like a regular button,
  120.  * except that it's oriented vertically rather than horizontally.
  121.  * bSet is the blob set to add the button blob to, r defines the
  122.  * bounds rect, and title is a string containing the text to be drawn
  123.  * in the blob.
  124.  * The title is copied into a new handle and the handle is stored into
  125.  * the blob's reference constant so the draw proc can tell what to draw
  126.  * later.
  127.  *
  128.  * The glueMax and mustMatch fields are assumed to be zero and false.
  129.  */
  130.  
  131. BlobHandle
  132. NewVButtonBlob (BlobSetHandle bSet, Rect *r, StringPtr title,
  133.                             Boolean visible)
  134. {
  135. BlobHandle    b;
  136. StringHandle    hStr;
  137. RgnHandle    rgn, rgn2;
  138.  
  139.     /*
  140.      * Make the regions defining the blob first.  The drag region is inset
  141.      * by one so that the text in the middle can be dimmed without dimming
  142.      * the frame.
  143.      */
  144.  
  145.     rgn = NewRgn ();
  146.     OpenRgn ();
  147.     FrameRoundRect (r, 10, 10);        /* 12 ? */
  148.     CloseRgn (rgn);
  149.     rgn2 = NewRgn ();
  150.     CopyRgn (rgn, rgn2);
  151.     InsetRgn (rgn2, 1, 1);
  152.  
  153.     /*    Now make the blob and define its image    */
  154.  
  155.     hStr = (StringHandle) NewHandle (title[0] + 1);
  156.     HLock ((Handle) hStr);
  157.     StrCpy (*hStr, title);
  158.     HUnlock ((Handle) hStr);
  159.     b = NewBlob (bSet, visible, 0, false, (long) hStr);
  160.     SetProcRgnBlob (b, DrawVButtonBlob, rgn2, rgn);
  161.     SetBlobFlags (b, bProcManualDimMask);        /* draw proc does own dimming */
  162.     DisposeRgn (rgn);
  163.     DisposeRgn (rgn2);
  164.     return (b);
  165. }
  166.  
  167.  
  168. /*
  169.  * Drawing proc for character blobs.  The drag region covers the entire
  170.  * blob, so the drag region is actually empty.  Thus the drawing procedure
  171.  * only looks at the drag region.
  172.  */
  173.  
  174. static pascal void
  175. DrawCharBlob (BlobHandle bDst, BlobHandle bSrc, short partCode)
  176. {
  177. GrafPtr        port;
  178. Boolean        canDrawGray;
  179. short        savedTextMode;
  180. Rect    r;
  181. char    c;
  182. short    h, v;
  183.  
  184.     if (partCode == inStatBlob)                /* irrelevant, since empty */
  185.         return;
  186.  
  187.     r = BDragBox (bDst);
  188.     c = (char) LoWord (GetBRefCon (bSrc));
  189.     EraseRoundRect (&r, 10, 10);
  190.     if (c == ' ')
  191.     {
  192.         FrameRoundRect (&r, 10, 10);
  193.     }
  194.     else
  195.     {
  196.         h = (r.left + r.right - CharWidth (c)) / 2;
  197.         v = r.bottom - 4;
  198.         MoveTo (h, v);
  199.         DrawChar (c);
  200.     }
  201. }
  202.  
  203.  
  204. /*
  205.  * Make a blob with a character in the middle (or a frame if the
  206.  * character is a space).    Pass all the normal NewBlob parameters
  207.  * except the reference constant, plus the horizontal and vertical
  208.  * coordinates, and the character to be drawn in the blob.
  209.  *
  210.  * The char is stored as the low word of the reference value.  The 
  211.  * application can put whatever it wants in the high word.
  212.  */
  213.  
  214. BlobHandle
  215. MakeCharBlob (BlobSetHandle bSet, Boolean enable, short glueMVal,
  216.                     Boolean mustMatch, short h, short v, char c)
  217. {
  218. BlobHandle    b;
  219. Rect        r;
  220.  
  221.     /*
  222.      * Make the regions defining the blob first.  The drag region is inset
  223.      * by one so that the text in the middle can be dimmed without dimming
  224.      * the frame.
  225.      */
  226.  
  227.     SetRect (&r, h, v, h + charBlobSize, v + charBlobSize);
  228.  
  229.     b = NewBlob (bSet, enable, glueMVal, mustMatch, (long) c);
  230.     SetProcRectBlob (b, DrawCharBlob, &r, &r);
  231.     return (b);
  232. }
  233.  
  234.  
  235. /*
  236.  * Set the size in which character blobs are created
  237.  */
  238.  
  239. void
  240. SetCharBlobSize (short size)
  241. {
  242.     charBlobSize = size;
  243. }
  244.  
  245.  
  246. /*
  247.  * Determine the rectangle that defines each element of a grid,
  248.  * and pass the rectangle to a blob-drawing proc.  The proc draws
  249.  * whatever goes into the element.  Creates blobs a row at a time.
  250.  */
  251.  
  252. void
  253. MakeBlobGrid (short rows, short cols, short hOff, short vOff,
  254.                     short hWidth, short vHeight, short hGap, short vGap,
  255.                     void (*p) (Rect *r))
  256. {
  257. short    i, j;
  258. short    h, v;
  259. Rect    r;
  260.  
  261.     for (j = 0; j < rows; ++j)
  262.     {
  263.         for (i = 0; i < cols; ++i)
  264.         {
  265.             h = hOff + i * (hGap + hWidth);
  266.             v = vOff + j * (vGap + vHeight);
  267.             SetRect (&r, h, v, h + hWidth, v + vHeight);
  268.             (*p) (&r);
  269.         }
  270.     }
  271. }
  272.  
  273.  
  274. /*
  275.  * Draw a grid with the given number of rows and columns.  The upper
  276.  * left-hand corner of the top element is at (hoff, voff).  The
  277.  * height and width of each element is vHeight and hWidth.  The horizontal
  278.  * and vertical gaps between elements are hGap and vGap.  A border is
  279.  * also drawn around the whole grid.
  280.  */
  281.  
  282. void
  283. DrawGrid (short rows, short cols, short hOff, short vOff,
  284.                 short hWidth, short vHeight, short hGap, short vGap)
  285. {
  286. short    i;
  287. short    h, v;
  288. short    len;
  289. Rect    r;
  290.  
  291.     hOff -=    hGap;
  292.     vOff -=    vGap;
  293.     PenSize    (hGap, vGap);
  294.     /*    draw vertical lines     */
  295.     len = rows * (vGap + vHeight);
  296.     for (i = 0; i <= cols; ++i)
  297.     {
  298.         h = hOff + i * (hGap + hWidth);
  299.         MoveTo (h, vOff);
  300.         LineTo (h, vOff    + len);
  301.     }
  302.     /*    draw horizontal    lines  */
  303.     len    = cols * (hGap + hWidth);
  304.     for (i = 0; i <= rows; ++i)
  305.     {
  306.         v = vOff + i * (vGap + vHeight);
  307.         MoveTo (hOff, v);
  308.         LineTo (hOff + len, v);
  309.     }
  310.     PenNormal ();
  311. }
  312.  
  313.  
  314. /*
  315.  * Routines to create or dispose of offscreen ports
  316.  */
  317.  
  318. GrafPtr
  319. NewOffPort (Rect *r)
  320. {
  321. GrafPtr    thePort, tmpPort;
  322. BitMap    *theMap;
  323. long    bitCount;
  324. short    rowBytes;
  325. Ptr        bits;
  326.  
  327.     rowBytes = ((r->right - r->left + 15) / 8) & (~1);
  328.     bitCount = rowBytes * (r->bottom - r->top);
  329.     bits = NewPtr (bitCount);
  330.     if (bits)
  331.     {
  332.         thePort = (GrafPtr) NewPtr ((long) sizeof (GrafPort));
  333.         if (thePort)
  334.         {
  335.             theMap = (BitMap *) NewPtr ((long) sizeof (BitMap));
  336.             if (theMap)
  337.             {
  338.                 theMap->bounds = *r;
  339.                 theMap->rowBytes = rowBytes;
  340.                 theMap->baseAddr = bits;
  341.                 GetPort    (&tmpPort);
  342.                 OpenPort (thePort);
  343.                 SetPortBits (theMap);
  344.                 PortSize (r->right - r->left, r->bottom - r->top);
  345.                 RectRgn (thePort->visRgn, &thePort->portRect);
  346.                 ClipRect (&thePort->portRect);
  347.                 EraseRect (&thePort->portRect);
  348.                 SetPort    (tmpPort);
  349.                 return (thePort);
  350.             }
  351.             DisposPtr ((Ptr) thePort);
  352.         }
  353.         DisposPtr (bits);
  354.     }
  355.     return (nil);
  356. }
  357.  
  358.  
  359. void
  360. DisposeOffPort (GrafPtr thePort)
  361. {
  362.     ClosePort (thePort);
  363.     DisposPtr (thePort->portBits.baseAddr);
  364.     DisposPtr ((Ptr) &thePort->portBits);
  365.     DisposPtr ((Ptr) thePort);
  366. }
  367.  
  368.  
  369. /*
  370.  * Board position drawing procedure.  All positions are drawn the
  371.  * same - a black rectangle.  However, the unused positions are set
  372.  * dimmed by InitBoard, so the drawing mechanisms make them gray.
  373.  * For the drag region of used positions,
  374.  * this proc is only called if the position has no piece (i.e., no
  375.  * glob) because the pieces are picture blobs.
  376.  *
  377.  * For these reasons, bSrc and bDst are always equal when
  378.  * DrawBoardPos is called.
  379.  */
  380.  
  381. static pascal void
  382. DrawBoardPos (BlobHandle bDst, BlobHandle bSrc, short partCode)
  383. {
  384. Rect    r;
  385.  
  386.     r = BStatBox (bDst);
  387.      PaintRect (&r);
  388. }
  389.  
  390.  
  391. /*
  392.  * Build a checkerboard, which consists of alternating black and gray
  393.  * squares.  They are actually the same as far as the drawing proc
  394.  * goes, but the gray squares are set to be dimmed so that the
  395.  * normal drawing mechanisms do the work of making the two types
  396.  * of square look distinct.  The fact that the gray squares are
  397.  * dimmed also makes the hit-testing mechanisms ignore them.
  398.  */
  399.  
  400. void
  401. MakeCheckerBoard (BlobSetHandle *boardBlobs, CheckerBoard *board, short pieceSize)
  402. {
  403. short        h, v;
  404. Rect        r, r2;
  405. BlobHandle    b;
  406.  
  407.     *boardBlobs = NewBlobSet ();
  408.     for (v = 0; v < 8; v++)
  409.     {
  410.         for (h = 0; h < 8; h++)
  411.         {
  412.             b = NewBlob (*boardBlobs, true, 0, false, 0L);
  413.             (*board)[h][v] = b;
  414.             SetRect (&r, 0, 0, pieceSize, pieceSize);
  415.             OffsetRect (&r, h * pieceSize, v * pieceSize);
  416.             r2 = r;
  417.             InsetRect (&r2, 1, 1);
  418.             SetProcRectBlob (b, DrawBoardPos, &r2, &r);
  419.  
  420.             /*
  421.              * All unused postions have coordinates that sum to an
  422.              * odd number.
  423.              */
  424.  
  425.             if ((h + v) % 2 == 1)
  426.                 SetBDrawMode (b, inFullBlob, dimDraw);
  427.         }
  428.     }
  429. }
  430.  
  431.  
  432. /*
  433.  * Make a set of checkers pieces and return the blob set handle.  The first
  434.  * blob in the set is the black piece; the second is the white piece.
  435.  */
  436.  
  437. BlobSetHandle
  438. MakeCheckersPieces (short pieceSize)
  439. {
  440. BlobSetHandle    bSet;
  441. BlobHandle    b;
  442. Rect        r;
  443.  
  444.     bSet = NewBlobSet ();
  445.     SetRect (&r, 0, 0, pieceSize - 1, pieceSize - 1);
  446.     b = NewBlob (bSet, true, infiniteGlue, false, 0L);
  447.     OpenBlob ();
  448.     PaintRect (&r);
  449.     PenMode (patBic);
  450.     FrameOval (&r);
  451.     PenNormal ();
  452.     CloseRectBlob (b, &r, &r);
  453.     b = NewBlob (bSet, true, infiniteGlue, false, 0L);
  454.     OpenBlob ();
  455.     PaintRect (&r);
  456.     EraseOval (&r);
  457.     CloseRectBlob (b, &r, &r);
  458.     return (bSet);
  459. }
  460.  
  461.  
  462. /*
  463.  * Given a blob handle, find the checkerboard position that corresponds to it.
  464.  * This is used to map hits in the blob set (a list) to the position in
  465.  * the board (a 2-d array).
  466.  */
  467.  
  468. void
  469. FindCheckerBoardPos (BlobHandle b, CheckerBoard *board, short *h, short *v)
  470. {
  471. short    i, j;
  472.  
  473.     for (i = 0; i < 8; ++i)
  474.     {
  475.         for (j = 0; j < 8; ++j)
  476.         {
  477.             if ((*board)[i][j] == b)
  478.             {
  479.                 *h = i;
  480.                 *v = j;
  481.                 return;
  482.             }
  483.         }
  484.     }
  485.     /* shouldn't ever get here */
  486. }
  487.  
  488.  
  489. /*
  490.  * Check whether a checkerboard position is empty.  The coordinates must be
  491.  * legal, the position must be used in the current configuration,
  492.  * and the position must have a piece on it.
  493.  */
  494.  
  495. Boolean
  496. CheckerBoardPosEmpty (CheckerBoard *board, short h, short v)
  497. {
  498.     return (h >= 0 && h < 8 && v >= 0 && v < 8
  499.             && (h + v) % 2 == 0
  500.             && BGlob ((*board)[h][v]) == nil);
  501. }
  502.